![logo](https://github.com/mmattamala/LogosFCFM/blob/master/Ciencias%20de%20la%20Computaci%C3%B3n/Logos%20Facultad/fcfm_dcc_png.png?raw=true =300x)
CC5206 - Introducción a la Minería de Datos
Profesora: Bárbara Poblete
Alumnos: \ Cristián Tamblay \ José Cañete \ Diego Díaz
Auxiliares: \ Hernán Sarmiento \ José Miguel Herrera
¿Cuál es el contexto general del tema/problema/datos que eligió estudiar?
¿Por qué podría ser de interés estos datos?
¿Qué es lo que les gustaría analizar utilizando estos datos? o ¿Qué problema les gustaría resolver utilizando estos datos?
¿Cómo se se puede hacer esto de forma preliminar?
Se plantean las siguientes hipótesis con respecto al dataset:
Instalación de librerías necesarias para poder visualizar los gráficos que contienen características del dataset
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
import plotly
import plotly.plotly as py
import plotly.graph_objs as go
plotly.tools.set_credentials_file(username='cristian.tamblay', api_key='OJwr2lNHDmoskz1vzRTb')
def mostrar_todo(df):
with pd.option_context('display.max_rows', None, 'display.max_columns', None):
print(df)
Verificar que output_all.csv esté en el entorno.
datos_problemas = pd.read_csv("output_all.csv",sep=";")
datos_problemas.head()
Lo primero es eliminar los problemas que no poseen descripción (main_text), pues no son un aporte al momento de llevar a cabo el análisis
datos_problemas = datos_problemas[pd.notnull(datos_problemas['main_text'])]
print(datos_problemas.shape)
Luego se arregla el formato de los tags para poder utilizarlos de mejor manera en los experimentos
datos_problemas.tags = datos_problemas.tags.apply(lambda x: [str(elem.strip()).replace("'", "") for elem in x[1:len(x)-1].split('/')])
datos_problemas.tags = datos_problemas.tags.transform(tuple)
datos_problemas = datos_problemas.reset_index(drop=True)
Lo siguiente que se hace es separar el dataset en dos: una parte que posee al menos un tag y otra que no posee tags. Esto pues los problemas con tag aportan más valor en los experimentos a realizar que aquellos sin tag.
datos_notageados = datos_problemas[datos_problemas.tags.apply(lambda x: (len(x) == 1 and '' in x))]
datos_tageados = datos_problemas[datos_problemas.tags.apply(lambda x: not(len(x) == 1 and '' in x))]
datos_tageados = datos_tageados.reset_index(drop=True)
Ahora lo que hará es armar el set de categorías, para luego construir un dataframe separado por éstas
categorias = []
for fila in datos_tageados.tags:
for cat in fila:
categorias.append(cat)
categorias = list(set(categorias))
Se crea un nuevo dataframe con columnas de cada categoría, las cuales contienen un 0 o un 1, dependiendo si el texto pertenece a esa categoría en particular o no
columns = ['main_text','tags'] + categorias
#print(columns)
datos_por_categoria = pd.DataFrame(columns=columns)
#datos_por_categoria.head()
datos_por_categoria.main_text = datos_tageados.main_text
datos_por_categoria.tags = datos_tageados.tags
#datos_por_categoria.head()
datos_por_categoria.fillna(0)
for columna in datos_por_categoria.columns:
#print("columna " + columna)
if (columna != 'main_text' and columna != 'tags'):
for index, fila in datos_por_categoria.iterrows():
#print("index " + str(index))
#print("fila " + str(fila))
if (columna in fila['tags']):
fila[columna] = 1
else:
fila[columna] = 0
datos_por_categoria.drop('tags', axis=1, inplace=True)
for categoria in categorias:
datos_tageados.loc[:,categoria] = datos_por_categoria[categoria]
print(datos_por_categoria.shape)
print(datos_tageados.shape)
print(datos_problemas.shape)
datos_por_categoria.head()
Ahora se crea un nuevo dataframe que se usará para clasificar la dificultad/letra de los problemas. Para esto sólo se usarán los problemas en los que las letras sean del conjunto {A, B, C, D, E, F, G, H}, pues las demás pertenecen en general a concursos especiales y que dificultarían la clasificación.
letras = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
#letras = ["A", 'B', 'C', 'D', 'E']
datos_por_dificultad = datos_tageados[datos_tageados.letter.apply(lambda x: (x in letras))]
datos_por_dificultad = datos_por_dificultad.reset_index(drop=True)
print(datos_por_dificultad.shape)
datos_por_dificultad.head()
cantidad = []
for i in range(0,len(datos_problemas.letter.unique())):
cantidad.append(len(datos_problemas[datos_problemas.letter == datos_problemas['letter'].unique()[i]]))
cantidadPorLetra = np.column_stack((np.asarray(cantidad),datos_problemas['letter'].unique()))
cantidadPorLetra=cantidadPorLetra[(-cantidadPorLetra[:,0]).argsort()] #El menos es decreasing
trace0 = go.Bar(
x=cantidadPorLetra[:,1],
y=cantidadPorLetra[:,0]
)
data=[trace0]
layout = go.Layout(
title='Cantidad de problemas en función de la dificultad',
xaxis=dict(
type='category',
title='Letras/Dificultades de los problemas'
),
yaxis=dict(
title='Cantidad de problemas'
)
)
fig=go.Figure(data=data, layout=layout)
py.iplot(fig, filename='letra')
Se analizarán ciertas características del dataset de problemas, partiendo por ver cúanto es el tiempo límite promedio en que deben resolverse.
cantidad = []
for i in range(0,len(datos_problemas.time_limit.unique())):
cantidad.append(len(datos_problemas[datos_problemas.time_limit == datos_problemas['time_limit'].unique()[i]]))
cantidadPorTiempo = np.column_stack((np.asarray(cantidad),datos_problemas['time_limit'].unique()))
cantidadPorTiempo=cantidadPorTiempo[(-cantidadPorTiempo[:,0]).argsort()] #El menos es decreasing
trace0 = go.Bar(
x=cantidadPorTiempo[:,1],
y=cantidadPorTiempo[:,0]
)
data=[trace0]
layout = go.Layout(
title='Cantidad de problemas en función del tiempo máximo',
xaxis=dict(
type='category',
title='Tiempo máximo para resolver el problema'
),
yaxis=dict(
title='Cantidad de problemas'
)
)
fig=go.Figure(data=data, layout=layout)
py.iplot(fig, filename='tiempo')
Se observa que la mayor parte de este dataset se divide entre los problemas de 1 y 2 segundos, lo que no nos aporta mucho sobre la clasificación de los problemas. Pueden haber problemas de temas muy distintos con el mismo tiempo de resolución. \ Haciendo el mismo análisis, pero esta vez midiendo la cantidad de memoria que utilizan los problemas, se llega a lo siguiente.
cantidad = []
for i in range(0,len(datos_problemas.memory_limit.unique())):
cantidad.append(len(datos_problemas[datos_problemas.memory_limit == datos_problemas['memory_limit'].unique()[i]]))
cantidadPorMemoria = np.column_stack((np.asarray(cantidad),datos_problemas['memory_limit'].unique()))
cantidadPorMemoria=cantidadPorMemoria[(-cantidadPorMemoria[:,0]).argsort()] #El menos es decreasing
trace0 = go.Bar(
x=cantidadPorMemoria[:,1],
y=cantidadPorMemoria[:,0]
)
data=[trace0]
layout = go.Layout(
title='Cantidad de problemas en función de la cantidad máxima de memoria disponible',
xaxis=dict(
type='category',
title='Cantidad máxima de memoria para resolver el problema'
),
yaxis=dict(
title='Cantidad de problemas'
)
)
fig=go.Figure(data=data, layout=layout)
py.iplot(fig, filename='memoria')
Se observa que casi todos los problemas tienen como límite los 256 MB de memoria. No se puede encontrar una rapida relación entre el tipo de problema y la cantidad de memoria entregada.
A continuación se observan los 25 tags más usados.
cantidad = []
posibles = []
for row in datos_problemas.tags:
for tag in row:
posibles.append(tag)
posibles = pd.Series(posibles).unique()
for t in range(0,len(posibles)):
if(posibles[t]==''):
cantidad.append(len(datos_problemas[datos_problemas.tags.isin((('',),))]))
else:
cantidad.append(len(datos_problemas[datos_problemas.tags.apply(lambda x : any((i for i in x if i.find(posibles[t]) >= 0)))]))
cantidadPorTag = np.column_stack((np.asarray(cantidad),np.asarray(posibles)))
cantidadPorTag=cantidadPorTag[(-cantidadPorTag[:,0]).argsort()] #El menos es decreasing
cantidadPorTag=cantidadPorTag[0:25,:]
trace0 = go.Bar(
x=cantidadPorTag[:,1],
y=cantidadPorTag[:,0]
)
data=[trace0]
layout = go.Layout(
title='Cantidad de problemas en función del tag',
xaxis=dict(
type='category',
title='Tag del problema'
),
yaxis=dict(
title='Cantidad de problemas'
)
)
fig=go.Figure(data=data, layout=layout)
py.iplot(fig, filename='tags')
Se ve que la mayoría de los problemas tiene como tag implementation, lo cual no dice mucho del problema. Adicionalmente, la segunda categoría más popular de problema son aquellos que nisiquiera poseen un tag descriptor, quedando ambigua la naturaleza de éste. Finalmente se puede observar que existen categorías que se repiten, pues están listadas con categorías adicionales, lo cual puede provocar una duplicación de problemas en caso de querer individualizarlos.
En primer lugar, dado que la mayoría de la información se desea obtener del texto (principal, de input y de output) se decidió hacer uso de la librería SKLearn que entre sus variados métodos ofrece la posibilidad de obtener Bag of Words a partir de texto, así como N-Gramas. En este caso particular se decidió probar el uso de Bag of Words de manera sencilla para ver qué tal funciona. Como resultado, con el siguiente código se puede ver el Bag of Words creado, donde cada texto inicial se convierte en un vector y se puede ver el vocabulario con las frecuencias de cada palabra en el conjunto de datos.
!pip install stopwords
!pip install nltk
import nltk
nltk.download('stopwords')
Se procesará la data de tal manera de filtrar aquellas palabras consideradas como stopwords con el propósito de no ensuciar los resultados que se vayan a obtener de los experimentos.
import re
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.dummy import DummyClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
import seaborn as sns
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import cross_validate
from sklearn.metrics import make_scorer, accuracy_score, precision_score, recall_score, f1_score
import warnings
warnings.filterwarnings("ignore")
train, test = train_test_split(datos_por_categoria, test_size=0, shuffle=True)
X_train = train.main_text
X_test = test.main_text
y_train = train.drop(['main_text'], axis=1)
y_test = test.drop(['main_text'], axis=1)
vectorizer = CountVectorizer(stop_words='english',binary=True)
scoring = {'accuracy' : make_scorer(accuracy_score),
'precision' : make_scorer(precision_score),
'recall' : make_scorer(recall_score),
'f1_score' : make_scorer(f1_score)}
X_train = vectorizer.fit_transform(X_train).todense()
X_test = vectorizer.transform(X_test).todense()
La clasificación para estos datos se realizará con 1 clasificador por etiqueta. Esta es una buena forma de manejar los problemas que tienen multi-label.
A continuación se llevarán a cabo y se observarán los resultados de diversos métodos de clasificación para luego poder comentar la eficacia a nivel general de cada uno y poder analizar cuáles produjeron mejores y peores resultados. Además, a cada uno de estos se les realizó un 6-fold cross validation.
classifiers = []
for i in range(0,36):
clf = MultinomialNB()
classifiers.append(clf)
val_acuracy=0
val_precision = 0
val_recall = 0
val_f1_score = 0
for i in range(0,36):
validacion = cross_validate(clf, X_train, y_train.iloc[:,i].tolist(), cv=5,scoring=scoring)
val_acuracy += validacion['test_accuracy'].mean()/36.0
val_precision += validacion['test_precision'].mean()/36.0
val_recall += validacion['test_recall'].mean()/36.0
val_f1_score += validacion['test_f1_score'].mean()/36.0
print("Accuracy: "+str(val_acuracy))
print("Precision: "+str(val_precision))
print("Recall: "+str(val_recall))
print("F1-Score: "+str(val_f1_score))
classifiers = []
for i in range(0,36):
clf = LinearSVC()
classifiers.append(clf)
val_acuracy=0
val_precision = 0
val_recall = 0
val_f1_score = 0
for i in range(0,36):
validacion = cross_validate(clf, X_train, y_train.iloc[:,i].tolist(), cv=5,scoring=scoring)
val_acuracy += validacion['test_accuracy'].mean()/36.0
val_precision += validacion['test_precision'].mean()/36.0
val_recall += validacion['test_recall'].mean()/36.0
val_f1_score += validacion['test_f1_score'].mean()/36.0
print("Accuracy: "+str(val_acuracy))
print("Precision: "+str(val_precision))
print("Recall: "+str(val_recall))
print("F1-Score: "+str(val_f1_score))
classifiers = []
for i in range(0,36):
clf = LogisticRegression(solver='sag')
classifiers.append(clf)
val_acuracy=0
val_precision = 0
val_recall = 0
val_f1_score = 0
for i in range(0,36):
validacion = cross_validate(clf, X_train, y_train.iloc[:,i].tolist(), cv=5,scoring=scoring)
val_acuracy += validacion['test_accuracy'].mean()/36.0
val_precision += validacion['test_precision'].mean()/36.0
val_recall += validacion['test_recall'].mean()/36.0
val_f1_score += validacion['test_f1_score'].mean()/36.0
print("Accuracy: "+str(val_acuracy))
print("Precision: "+str(val_precision))
print("Recall: "+str(val_recall))
print("F1-Score: "+str(val_f1_score))
Para este clasificador en particuar se utilizará una red neuronal con capa oculta de 15 neuronas.
classifiers = []
for i in range(0,36):
clf = MLPClassifier(activation='relu',hidden_layer_sizes=(15,))
classifiers.append(clf)
val_acuracy=0
val_precision = 0
val_recall = 0
val_f1_score = 0
for i in range(0,36):
print(i)
validacion = cross_validate(clf, X_train, y_train.iloc[:,i].tolist(), cv=5,scoring=scoring)
val_acuracy += validacion['test_accuracy'].mean()/36.0
val_precision += validacion['test_precision'].mean()/36.0
val_recall += validacion['test_recall'].mean()/36.0
val_f1_score += validacion['test_f1_score'].mean()/36.0
print("Accuracy: "+str(val_acuracy))
print("Precision: "+str(val_precision))
print("Recall: "+str(val_recall))
print("F1-Score: "+str(val_f1_score))
classifiers = []
for i in range(0,36):
clf = RandomForestClassifier()
classifiers.append(clf)
val_acuracy=0
val_precision = 0
val_recall = 0
val_f1_score = 0
for i in range(0,36):
validacion = cross_validate(clf, X_train, y_train.iloc[:,i].tolist(), cv=5,scoring=scoring)
val_acuracy += validacion['test_accuracy'].mean()/36.0
val_precision += validacion['test_precision'].mean()/36.0
val_recall += validacion['test_recall'].mean()/36.0
val_f1_score += validacion['test_f1_score'].mean()/36.0
print("Accuracy: "+str(val_acuracy))
print("Precision: "+str(val_precision))
print("Recall: "+str(val_recall))
print("F1-Score: "+str(val_f1_score))
classifiers = []
for i in range(0,36):
clf = DummyClassifier(strategy='uniform')
classifiers.append(clf)
val_acuracy=0
val_precision = 0
val_recall = 0
val_f1_score = 0
for i in range(0,36):
validacion = cross_validate(clf, X_train, y_train.iloc[:,i].tolist(), cv=5,scoring=scoring)
val_acuracy += validacion['test_accuracy'].mean()/36.0
val_precision += validacion['test_precision'].mean()/36.0
val_recall += validacion['test_recall'].mean()/36.0
val_f1_score += validacion['test_f1_score'].mean()/36.0
print("Accuracy: "+str(val_acuracy))
print("Precision: "+str(val_precision))
print("Recall: "+str(val_recall))
print("F1-Score: "+str(val_f1_score))
Al concluir esta ronda inicial de experimentos se puede observar que aquel con mejor precisión fue el clasificador de Naïve Bayes con una precisión de 46%. En cuanto al peor método, se incluyó el clasificador Dummy con el propósito de exponer lo ineficiente que es como clasificador, logrando una precisión de tan sólo un 5%. Sin embargo, se esperaba que los resultados de este último clasificador fueran malos, por tanto si se analizan los resultados de los otros clasificadores usados, el peor corresponde en realidad al clasificador SVC, con una precisión de tan sólo 33%.
datos_clasificacion_dificultad = pd.DataFrame(columns=['main_text', 'letter'])
datos_clasificacion_dificultad.main_text = datos_por_dificultad.main_text
datos_clasificacion_dificultad.letter = datos_por_dificultad.letter
datos_clasificacion_dificultad = datos_clasificacion_dificultad[pd.notnull(datos_clasificacion_dificultad['letter'])]
train, test = train_test_split(datos_clasificacion_dificultad, test_size=0.33, shuffle=True)
X_train = train.main_text
X_test = test.main_text
y_train = train.drop(['main_text'], axis=1).letter.ravel()
y_test = test.drop(['main_text'], axis=1).letter.ravel()
vectorizer = CountVectorizer(stop_words='english')
#vectorizer = TfidfVectorizer(stop_words='english')
X_train = vectorizer.fit_transform(X_train).todense()
X_test = vectorizer.transform(X_test).todense()
### COMPLETAR ESTE CÓDIGO
## run_classifier recibe un clasificador, un dataset (X, y)
## y opcionalmente la cantidad de resultados que se quiere obtener del clasificador
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, recall_score, precision_score
def run_classifier(clf, X_train, X_test, y_train, y_test, num_tests=100):
metrics = {'f1-score': [], 'precision': [], 'recall': []}
for _ in range(num_tests):
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)
### FIN COMPLETAR ACÁ
metrics['f1-score'].append(f1_score(y_test, predictions, average='micro')) # X_test y y_test deben ser definidos previamente
metrics['recall'].append(recall_score(y_test, predictions, average=None))
metrics['precision'].append(precision_score(y_test, predictions, average='micro'))
return metrics
## ejecutar este código
from sklearn.svm import SVC # support vector machine classifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB # naive bayes
from sklearn.neighbors import KNeighborsClassifier
from sklearn.dummy import DummyClassifier
from sklearn.multioutput import MultiOutputClassifier
from sklearn.naive_bayes import BernoulliNB
from sklearn.tree import ExtraTreeClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.semi_supervised import LabelPropagation
from sklearn.semi_supervised import LabelSpreading
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.svm import LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import LogisticRegressionCV
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import NearestCentroid
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
from sklearn.neighbors import RadiusNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import RidgeClassifier
from sklearn.linear_model import RidgeClassifierCV
c0 = ("Base Dummy", DummyClassifier())
c1 = ("Decision Tree", DecisionTreeClassifier())
c2 = ("Gaussian Naive Bayes", GaussianNB())
c3 = ("KNN", KNeighborsClassifier(n_neighbors=8))
c4 = ("Bernoulli Naive Bayes", BernoulliNB())
c5 = ("Extra Tree", ExtraTreeClassifier())
c6 = ("Extra Trees", ExtraTreesClassifier())
c7 = ("Label Propagation", LabelPropagation())
c8 = ("Label Spreading", LabelSpreading())
c9 = ("Linear Discriminant Analysis", LinearDiscriminantAnalysis())
c10 = ("Linear SVC", LinearSVC())
#c11 = ("Logistic Regression", LogisticRegression(multi_class="multinomial", solver="saga"))
#c12 = ("Logistic Regression CV", LogisticRegressionCV(multi_class="multinomial", solver="saga"))
c13 = ("Multi Layer Perceptron", MLPClassifier())
c14 = ("Nearest Centroid", NearestCentroid())
c15 = ("Quadratic Discriminant Analysis", QuadraticDiscriminantAnalysis())
#c16 = ("Radius Neighbors", RadiusNeighborsClassifier())
c17 = ("Random Forest", RandomForestClassifier())
c18 = ("Ridge Classifier", RidgeClassifier())
c19 = ("Ridge ClassifierCV", RidgeClassifierCV())
classifiers = [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c13, c14, c15, c17, c18, c19]
for name, clf in classifiers:
metrics = run_classifier(clf, X_train, X_test, y_train, y_test, num_tests=1) # hay que implementarla en el bloque anterior.
print("----------------")
print("Resultados para clasificador: ",name)
print("Precision promedio:",np.array(metrics['precision']).mean())
print("Recall promedio:",np.array(metrics['recall']).mean())
print("F1-score promedio:",np.array(metrics['f1-score']).mean())
print("----------------\n\n")
print("FIN")
columns = ['letter'] + categorias
datos_clasificacion_dificultad = pd.DataFrame(columns=columns)
datos_clasificacion_dificultad.letter = datos_por_dificultad.letter
for categoria in categorias:
datos_clasificacion_dificultad[categoria] = datos_por_dificultad[categoria]
datos_clasificacion_dificultad = datos_clasificacion_dificultad[pd.notnull(datos_clasificacion_dificultad['letter'])]
datos_clasificacion_dificultad = datos_clasificacion_dificultad.reset_index(drop=True)
train, test = train_test_split(datos_clasificacion_dificultad, test_size=0.33, shuffle=True)
y_train = train.letter.ravel()
y_test = test.letter.ravel()
X_train = train.drop(['letter'], axis=1)
X_test = test.drop(['letter'], axis=1)
## ejecutar este código
from sklearn.svm import SVC # support vector machine classifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB # naive bayes
from sklearn.neighbors import KNeighborsClassifier
from sklearn.dummy import DummyClassifier
from sklearn.multioutput import MultiOutputClassifier
from sklearn.naive_bayes import BernoulliNB
from sklearn.tree import ExtraTreeClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.semi_supervised import LabelPropagation
from sklearn.semi_supervised import LabelSpreading
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.svm import LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import LogisticRegressionCV
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import NearestCentroid
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
from sklearn.neighbors import RadiusNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import RidgeClassifier
from sklearn.linear_model import RidgeClassifierCV
c0 = ("Base Dummy", DummyClassifier())
c1 = ("Decision Tree", DecisionTreeClassifier())
c2 = ("Gaussian Naive Bayes", GaussianNB())
c3 = ("KNN", KNeighborsClassifier(n_neighbors=8))
c4 = ("Bernoulli Naive Bayes", BernoulliNB())
c5 = ("Extra Tree", ExtraTreeClassifier())
c6 = ("Extra Trees", ExtraTreesClassifier())
c7 = ("Label Propagation", LabelPropagation())
c8 = ("Label Spreading", LabelSpreading())
c9 = ("Linear Discriminant Analysis", LinearDiscriminantAnalysis())
c10 = ("Linear SVC", LinearSVC())
#c11 = ("Logistic Regression", LogisticRegression(multi_class="multinomial", solver="saga"))
#c12 = ("Logistic Regression CV", LogisticRegressionCV(multi_class="multinomial", solver="saga"))
c13 = ("Multi Layer Perceptron", MLPClassifier())
c14 = ("Nearest Centroid", NearestCentroid())
c15 = ("Quadratic Discriminant Analysis", QuadraticDiscriminantAnalysis())
#c16 = ("Radius Neighbors", RadiusNeighborsClassifier())
c17 = ("Random Forest", RandomForestClassifier())
c18 = ("Ridge Classifier", RidgeClassifier())
c19 = ("Ridge ClassifierCV", RidgeClassifierCV())
classifiers = [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c13, c14, c15, c17, c18, c19]
for name, clf in classifiers:
metrics = run_classifier(clf, X_train, X_test, y_train, y_test, num_tests=10) # hay que implementarla en el bloque anterior.
print("----------------")
print("Resultados para clasificador: ",name)
print("Precision promedio:",np.array(metrics['precision']).mean())
print("Recall promedio:",np.array(metrics['recall']).mean())
print("F1-score promedio:",np.array(metrics['f1-score']).mean())
print("----------------\n\n")
print("FIN")
Para concluir, nos concentraremos en comparar precision y F1 score, ya que nuestro foco es qué tan bien se clasifican los positivos y además cuántos de los positivos fueron ignorados.
En el caso de clasificar los tags por el 'main_text', el clasificador SVC obtiene el mejor rendimiento. Por el contrario, el que tiene el peor rendimiento es Naïve Bayes, pese a que tiene la precisión más alta (hace pocos intentos pero buenos).
Continuando con el caso de la dificultad en base al texto, el mejor clasificador es el basado en Random Forest, aunque la mayoría de los clasificadores están al nivel del Dummy.
Terminando con el caso de la dificultad en base a los tags, el mejor clasificador es Bernoulli Naïve Bayes.